package com.koushikdutta.async.http;

import android.annotation.SuppressLint;
import android.net.Uri;
import android.os.Build.VERSION;
import android.text.TextUtils;
import com.koushikdutta.async.AsyncSSLException;
import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.DataEmitter;
import com.koushikdutta.async.NullDataCallback;
import com.koushikdutta.async.callback.ConnectCallback;
import com.koushikdutta.async.future.Cancellable;
import com.koushikdutta.async.future.Future;
import com.koushikdutta.async.future.SimpleFuture;
import com.koushikdutta.async.http.AsyncHttpClientMiddleware.OnRequestCompleteData;
import com.koushikdutta.async.http.callback.HttpConnectCallback;
import com.koushikdutta.async.http.libcore.RawHeaders;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.ProxySelector;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeoutException;

public class AsyncHttpClient {
    static final /* synthetic */ boolean $assertionsDisabled = (!AsyncHttpClient.class.desiredAssertionStatus());
    private static AsyncHttpClient mDefaultInstance;
    final ArrayList<AsyncHttpClientMiddleware> mMiddleware = new ArrayList();
    AsyncServer mServer;
    AsyncSocketMiddleware socketMiddleware;
    AsyncSSLSocketMiddleware sslSocketMiddleware;

    public interface WebSocketConnectCallback {
        void onCompleted(Exception exception, WebSocket webSocket);
    }

    private class FutureAsyncHttpResponse extends SimpleFuture<AsyncHttpResponse> {
        public Object scheduled;
        public AsyncSocket socket;
        public Runnable timeoutRunnable;

        private FutureAsyncHttpResponse() {
        }

        public boolean cancel() {
            if (!super.cancel()) {
                return false;
            }
            if (this.socket != null) {
                this.socket.setDataCallback(new NullDataCallback());
                this.socket.close();
            }
            if (this.scheduled != null) {
                AsyncHttpClient.this.mServer.removeAllCallbacks(this.scheduled);
            }
            return true;
        }
    }

    public static AsyncHttpClient getDefaultInstance() {
        if (mDefaultInstance == null) {
            mDefaultInstance = new AsyncHttpClient(AsyncServer.getDefault());
        }
        return mDefaultInstance;
    }

    public ArrayList<AsyncHttpClientMiddleware> getMiddleware() {
        return this.mMiddleware;
    }

    public void insertMiddleware(AsyncHttpClientMiddleware middleware) {
        this.mMiddleware.add(0, middleware);
    }

    public AsyncHttpClient(AsyncServer server) {
        this.mServer = server;
        AsyncHttpClientMiddleware asyncSocketMiddleware = new AsyncSocketMiddleware(this);
        this.socketMiddleware = asyncSocketMiddleware;
        insertMiddleware(asyncSocketMiddleware);
        asyncSocketMiddleware = new AsyncSSLSocketMiddleware(this);
        this.sslSocketMiddleware = asyncSocketMiddleware;
        insertMiddleware(asyncSocketMiddleware);
    }

    @SuppressLint({"NewApi"})
    private static void setupAndroidProxy(AsyncHttpRequest request) {
        if (request.proxyHost == null) {
            try {
                List<Proxy> proxies = ProxySelector.getDefault().select(URI.create(request.getUri().toString()));
                if (!proxies.isEmpty()) {
                    Proxy proxy = (Proxy) proxies.get(0);
                    if (proxy.type() == Type.HTTP && (proxy.address() instanceof InetSocketAddress)) {
                        String proxyHost;
                        InetSocketAddress proxyAddress = (InetSocketAddress) proxy.address();
                        if (VERSION.SDK_INT >= 14) {
                            proxyHost = proxyAddress.getHostString();
                        } else {
                            InetAddress address = proxyAddress.getAddress();
                            if (address != null) {
                                proxyHost = address.getHostAddress();
                            } else {
                                proxyHost = proxyAddress.getHostName();
                            }
                        }
                        request.enableProxy(proxyHost, proxyAddress.getPort());
                    }
                }
            } catch (Exception e) {
            }
        }
    }

    public AsyncSocketMiddleware getSocketMiddleware() {
        return this.socketMiddleware;
    }

    public AsyncSSLSocketMiddleware getSSLSocketMiddleware() {
        return this.sslSocketMiddleware;
    }

    public Future<AsyncHttpResponse> execute(AsyncHttpRequest request, HttpConnectCallback callback) {
        FutureAsyncHttpResponse ret = new FutureAsyncHttpResponse();
        execute(request, 0, ret, callback);
        return ret;
    }

    private void reportConnectedCompleted(FutureAsyncHttpResponse cancel, Exception ex, AsyncHttpResponseImpl response, AsyncHttpRequest request, HttpConnectCallback callback) {
        if ($assertionsDisabled || callback != null) {
            boolean complete;
            this.mServer.removeAllCallbacks(cancel.scheduled);
            if (ex != null) {
                request.loge("Connection error", ex);
                complete = cancel.setComplete(ex);
            } else {
                request.logd("Connection successful");
                complete = cancel.setComplete((Object) response);
            }
            if (complete) {
                callback.onConnectCompleted(ex, response);
                if (!$assertionsDisabled && ex == null && response.getSocket() != null && response.getDataCallback() == null && !response.isPaused()) {
                    throw new AssertionError();
                }
                return;
            } else if (response != null) {
                response.setDataCallback(new NullDataCallback());
                response.close();
                return;
            } else {
                return;
            }
        }
        throw new AssertionError();
    }

    private void execute(AsyncHttpRequest request, int redirectCount, FutureAsyncHttpResponse cancel, HttpConnectCallback callback) {
        if (this.mServer.isAffinityThread()) {
            executeAffinity(request, redirectCount, cancel, callback);
            return;
        }
        final AsyncHttpRequest asyncHttpRequest = request;
        final int i = redirectCount;
        final FutureAsyncHttpResponse futureAsyncHttpResponse = cancel;
        final HttpConnectCallback httpConnectCallback = callback;
        this.mServer.post(new Runnable() {
            public void run() {
                AsyncHttpClient.this.executeAffinity(asyncHttpRequest, i, futureAsyncHttpResponse, httpConnectCallback);
            }
        });
    }

    private static long getTimeoutRemaining(AsyncHttpRequest request) {
        return (long) request.getTimeout();
    }

    private static void copyHeader(AsyncHttpRequest from, AsyncHttpRequest to, String header) {
        String value = from.getHeaders().getHeaders().get(header);
        if (!TextUtils.isEmpty(value)) {
            to.getHeaders().getHeaders().set(header, value);
        }
    }

    private void executeAffinity(AsyncHttpRequest request, int redirectCount, FutureAsyncHttpResponse cancel, HttpConnectCallback callback) {
        if (!$assertionsDisabled && !this.mServer.isAffinityThread()) {
            throw new AssertionError();
        } else if (redirectCount > 15) {
            reportConnectedCompleted(cancel, new RedirectLimitExceededException("too many redirects"), null, request, callback);
        } else {
            final Uri uri = request.getUri();
            final OnRequestCompleteData data = new OnRequestCompleteData();
            request.executionTime = System.currentTimeMillis();
            data.request = request;
            request.logd("Executing request.");
            if (request.getTimeout() > 0) {
                final FutureAsyncHttpResponse futureAsyncHttpResponse = cancel;
                final AsyncHttpRequest asyncHttpRequest = request;
                final HttpConnectCallback httpConnectCallback = callback;
                cancel.timeoutRunnable = new Runnable() {
                    public void run() {
                        if (data.socketCancellable != null) {
                            data.socketCancellable.cancel();
                            if (data.socket != null) {
                                data.socket.close();
                            }
                        }
                        AsyncHttpClient.this.reportConnectedCompleted(futureAsyncHttpResponse, new TimeoutException(), null, asyncHttpRequest, httpConnectCallback);
                    }
                };
                cancel.scheduled = this.mServer.postDelayed(cancel.timeoutRunnable, getTimeoutRemaining(request));
            }
            final AsyncHttpRequest asyncHttpRequest2 = request;
            final FutureAsyncHttpResponse futureAsyncHttpResponse2 = cancel;
            final OnRequestCompleteData onRequestCompleteData = data;
            final HttpConnectCallback httpConnectCallback2 = callback;
            final int i = redirectCount;
            data.connectCallback = new ConnectCallback() {
                public void onConnectCompleted(Exception ex, AsyncSocket socket) {
                    asyncHttpRequest2.logv("socket connected");
                    if (!futureAsyncHttpResponse2.isCancelled()) {
                        if (futureAsyncHttpResponse2.timeoutRunnable != null) {
                            AsyncHttpClient.this.mServer.removeAllCallbacks(futureAsyncHttpResponse2.scheduled);
                        }
                        onRequestCompleteData.socket = socket;
                        synchronized (AsyncHttpClient.this.mMiddleware) {
                            Iterator i$ = AsyncHttpClient.this.mMiddleware.iterator();
                            while (i$.hasNext()) {
                                ((AsyncHttpClientMiddleware) i$.next()).onSocket(onRequestCompleteData);
                            }
                        }
                        futureAsyncHttpResponse2.socket = socket;
                        if (ex != null) {
                            AsyncHttpClient.this.reportConnectedCompleted(futureAsyncHttpResponse2, ex, null, asyncHttpRequest2, httpConnectCallback2);
                            return;
                        }
                        new AsyncHttpResponseImpl(asyncHttpRequest2) {
                            protected void onRequestCompleted(Exception ex) {
                                asyncHttpRequest2.logv("request completed");
                                if (!futureAsyncHttpResponse2.isCancelled() && futureAsyncHttpResponse2.timeoutRunnable != null && onRequestCompleteData.headers == null) {
                                    AsyncHttpClient.this.mServer.removeAllCallbacks(futureAsyncHttpResponse2.scheduled);
                                    futureAsyncHttpResponse2.scheduled = AsyncHttpClient.this.mServer.postDelayed(futureAsyncHttpResponse2.timeoutRunnable, AsyncHttpClient.getTimeoutRemaining(asyncHttpRequest2));
                                }
                            }

                            public void setDataEmitter(DataEmitter emitter) {
                                onRequestCompleteData.bodyEmitter = emitter;
                                synchronized (AsyncHttpClient.this.mMiddleware) {
                                    Iterator i$ = AsyncHttpClient.this.mMiddleware.iterator();
                                    while (i$.hasNext()) {
                                        ((AsyncHttpClientMiddleware) i$.next()).onBodyDecoder(onRequestCompleteData);
                                    }
                                }
                                this.mHeaders = onRequestCompleteData.headers;
                                super.setDataEmitter(onRequestCompleteData.bodyEmitter);
                                RawHeaders headers = this.mHeaders.getHeaders();
                                int responseCode = headers.getResponseCode();
                                if ((responseCode == 301 || responseCode == 302 || responseCode == 307) && asyncHttpRequest2.getFollowRedirect()) {
                                    String location = headers.get("Location");
                                    try {
                                        Uri redirect = Uri.parse(location);
                                        if (redirect.getScheme() == null) {
                                            redirect = Uri.parse(new URL(new URL(uri.toString()), location).toString());
                                        }
                                        AsyncHttpRequest asyncHttpRequest = new AsyncHttpRequest(redirect, asyncHttpRequest2.getMethod().equals("HEAD") ? "HEAD" : "GET");
                                        asyncHttpRequest.executionTime = asyncHttpRequest2.executionTime;
                                        asyncHttpRequest.logLevel = asyncHttpRequest2.logLevel;
                                        asyncHttpRequest.LOGTAG = asyncHttpRequest2.LOGTAG;
                                        asyncHttpRequest.proxyHost = asyncHttpRequest2.proxyHost;
                                        asyncHttpRequest.proxyPort = asyncHttpRequest2.proxyPort;
                                        AsyncHttpClient.setupAndroidProxy(asyncHttpRequest);
                                        AsyncHttpClient.copyHeader(asyncHttpRequest2, asyncHttpRequest, "User-Agent");
                                        AsyncHttpClient.copyHeader(asyncHttpRequest2, asyncHttpRequest, "Range");
                                        asyncHttpRequest2.logi("Redirecting");
                                        asyncHttpRequest.logi("Redirected");
                                        AsyncHttpClient.this.execute(asyncHttpRequest, i + 1, futureAsyncHttpResponse2, httpConnectCallback2);
                                        setDataCallback(new NullDataCallback());
                                        return;
                                    } catch (Exception e) {
                                        AsyncHttpClient.this.reportConnectedCompleted(futureAsyncHttpResponse2, e, this, asyncHttpRequest2, httpConnectCallback2);
                                        return;
                                    }
                                }
                                asyncHttpRequest2.logv("Final (post cache response) headers:\n" + this.mHeaders.getHeaders().toHeaderString());
                                AsyncHttpClient.this.reportConnectedCompleted(futureAsyncHttpResponse2, null, this, asyncHttpRequest2, httpConnectCallback2);
                            }

                            protected void onHeadersReceived() {
                                try {
                                    if (!futureAsyncHttpResponse2.isCancelled()) {
                                        if (futureAsyncHttpResponse2.timeoutRunnable != null) {
                                            AsyncHttpClient.this.mServer.removeAllCallbacks(futureAsyncHttpResponse2.scheduled);
                                        }
                                        asyncHttpRequest2.logv("Received headers:\n" + this.mHeaders.getHeaders().toHeaderString());
                                        onRequestCompleteData.headers = this.mHeaders;
                                        synchronized (AsyncHttpClient.this.mMiddleware) {
                                            Iterator i$ = AsyncHttpClient.this.mMiddleware.iterator();
                                            while (i$.hasNext()) {
                                                ((AsyncHttpClientMiddleware) i$.next()).onHeadersReceived(onRequestCompleteData);
                                            }
                                        }
                                        this.mHeaders = onRequestCompleteData.headers;
                                    }
                                } catch (Exception ex) {
                                    AsyncHttpClient.this.reportConnectedCompleted(futureAsyncHttpResponse2, ex, null, asyncHttpRequest2, httpConnectCallback2);
                                }
                            }

                            protected void report(Exception ex) {
                                if (ex != null) {
                                    asyncHttpRequest2.loge("exception during response", ex);
                                }
                                if (!futureAsyncHttpResponse2.isCancelled()) {
                                    if (ex instanceof AsyncSSLException) {
                                        asyncHttpRequest2.loge("SSL Exception", ex);
                                        AsyncSSLException ase = (AsyncSSLException) ex;
                                        asyncHttpRequest2.onHandshakeException(ase);
                                        if (ase.getIgnore()) {
                                            return;
                                        }
                                    }
                                    AsyncSocket socket = getSocket();
                                    if (socket != null) {
                                        super.report(ex);
                                        if (!((socket.isOpen() && ex == null) || getHeaders() != null || ex == null)) {
                                            AsyncHttpClient.this.reportConnectedCompleted(futureAsyncHttpResponse2, ex, null, asyncHttpRequest2, httpConnectCallback2);
                                        }
                                        onRequestCompleteData.exception = ex;
                                        synchronized (AsyncHttpClient.this.mMiddleware) {
                                            Iterator i$ = AsyncHttpClient.this.mMiddleware.iterator();
                                            while (i$.hasNext()) {
                                                ((AsyncHttpClientMiddleware) i$.next()).onRequestComplete(onRequestCompleteData);
                                            }
                                        }
                                    }
                                }
                            }

                            public AsyncSocket detachSocket() {
                                asyncHttpRequest2.logd("Detaching socket");
                                AsyncSocket socket = getSocket();
                                if (socket == null) {
                                    return null;
                                }
                                socket.setWriteableCallback(null);
                                socket.setClosedCallback(null);
                                socket.setEndCallback(null);
                                socket.setDataCallback(null);
                                setSocket(null);
                                return socket;
                            }
                        }.setSocket(socket);
                    } else if (socket != null) {
                        socket.close();
                    }
                }
            };
            setupAndroidProxy(request);
            synchronized (this.mMiddleware) {
                Iterator i$ = this.mMiddleware.iterator();
                while (i$.hasNext()) {
                    Cancellable socketCancellable = ((AsyncHttpClientMiddleware) i$.next()).getSocket(data);
                    if (socketCancellable != null) {
                        data.socketCancellable = socketCancellable;
                        cancel.setParent(socketCancellable);
                        return;
                    }
                }
                Exception unsupportedURI = new IllegalArgumentException("invalid uri=" + uri + " middlewares=" + this.mMiddleware);
                reportConnectedCompleted(cancel, unsupportedURI, null, request, callback);
            }
        }
    }

    public Future<WebSocket> websocket(final AsyncHttpRequest req, String protocol, final WebSocketConnectCallback callback) {
        WebSocketImpl.addWebSocketUpgradeHeaders(req, protocol);
        final SimpleFuture<WebSocket> ret = new SimpleFuture();
        ret.setParent(execute(req, new HttpConnectCallback() {
            public void onConnectCompleted(Exception ex, AsyncHttpResponse response) {
                if (ex == null) {
                    Object ws = WebSocketImpl.finishHandshake(req.getHeaders().getHeaders(), response);
                    if (ws == null) {
                        if (!ret.setComplete(new WebSocketHandshakeException("Unable to complete websocket handshake"))) {
                            return;
                        }
                    } else if (!ret.setComplete(ws)) {
                        return;
                    }
                    if (callback != null) {
                        callback.onCompleted(ex, ws);
                    }
                } else if (ret.setComplete(ex) && callback != null) {
                    callback.onCompleted(ex, null);
                }
            }
        }));
        return ret;
    }

    public Future<WebSocket> websocket(String uri, String protocol, WebSocketConnectCallback callback) {
        return websocket(new AsyncHttpGet(uri.replace("ws://", "http://").replace("wss://", "https://")), protocol, callback);
    }

    public AsyncServer getServer() {
        return this.mServer;
    }
}
